#!/bin/bash
#
# ipbl: A blocking tool of hooligans IPs using iptables, with a blacklist and whilelist files
# Copyright (C) 2012 ArabOSG, http://arabosg.org
# Project url: http://ipbl.projects.arabosg.org
# Author: Mohammed Shannaq , http://irbidnet.com
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
VER="0.0"
CNF="conf.ipbl"
ARGPRC="lib/argv_parser"
LCLBL="blacklist.lst"
STFUCNS="lib/stfuncs"
#who can run this script
ROOT_UID=0     # Only users with $UID 0 have root privileges.

#Errors No. begin
E_ERRORGETTINGSRC=10 #error while getting source files
E_NOTROOT=87   # Non-root exit error.
E_INVALIDIP=500 #INVALID IP GIVEN
#Errors No. end

# Run as root, of course.
if [ "$UID" -ne "$ROOT_UID" ]
then
  echo "You Must be root to run this script."
  exit $E_NOTROOT
fi

#get the content of config file
if [ -f "$CNF" ] && [ ! "$CNF" == "" ]; then
   source $CNF
else
   echo "$CNF not found; aborting"
   exit $E_ERRORGETTINGSRC
fi

#get the content of STFUCNS output and logging functions
if [ -f "$STFUCNS" ] && [ ! "$STFUCNS" == "" ]; then
   source $STFUCNS
else
   echo "$STFUCNS not found; aborting"
   exit $E_ERRORGETTINGSRC
fi

# Minimum number of arguments needed by this program
MINARGS=1

# define the names of flags as a regular expression
# flags are command line options that require arguments
flags="(d|a)"
declare d a                # flags

# define the names of switches as a regular expression
# Switches are command line options that do not take arguments.
# Make sure multi-char switches precede single-char switches in the regular expression.
# Note that the regular expression contains neither the special read-from-stdin switch "-" 
# nor the special end-of-options switch "--".
switches="(p|U|fresh|blit|silent|S)"
declare p U fresh blit silent S                                            # switches

#exporing path
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/bin
export IFS=$' \t\n'






#this function print the header of the script
function echo_header(){
        echo "ipbl -> IP blocking tool using iptables. reffer for README for more info"
        echo "copyright (c) 2012 Mohammed Shannaq, http://irbidnet.com"
        echo "http://www.irbidnet.com/ipbl"
        echo "for more help refer for REAME file of type ./ipbl -h"
        echo
}
echo_header


usage="usage: $(basename "$0") [-a ip] [-d ip] [-fresh] [-p] [-U] [-S]";

#this function  show program usage
show_usage() {
echo "$(basename "$0") Usage:"
echo ""
echo "$(basename "$0") -d {ip}"
echo " block (deny) the given IP or range of IPs on the fly"
echo " example: $(basename "$0") -d 192.168.210.50"
echo "          $(basename "$0") -d 192.168.210.50/24"
echo " you can use --blit switch with the -d flags to add the ip to the local blacklist also."
echo " example: $(basename "$0") -d 192.168.210.50 --blit"
echo 
echo "$(basename "$0") --fresh"
echo " make sure from all blacklisted IP(s) is denied and all whitelisted IP(s) is allowed"
echo " example: $(basename "$0") --fresh"
echo
echo "Special parameters:"
echo
echo "-S, --silent : running the tool in silent mode nothing will be printed to the terminal even normal errors"
echo " example: $(basename "$0") --fresh --silent"
echo
echo "$(basename "$0") -U"
echo " checking for software update (does not update just checking for any updates)"
echo
exit
}

# show usage if '-h' or  '--help' is the first argument or no argument is given
case $1 in
	""|"-h"|"--help") show_usage ;;
esac

# get the number of command-line arguments given
ARGC=$#

# check to make sure enough arguments were given or exit
if [[ $ARGC -lt $MINARGS ]] ; then
 echo "Too few arguments given (Minimum:$MINARGS)"
 echo "type -h for help or refer for README"
 exit 1
fi

#get the content of args command processoing file
if [ -f "$ARGPRC" ] && [ ! "$ARGPRC" == "" ]; then
   source $ARGPRC
else
   echo "$ARGPRC not found; aborting"
   exit $E_ERRORGETTINGSRC
fi






#####
#this function validate the gevin ip. it also accept ip ranges using the CIDR
function valid_ip()
{
	local  ip=$1
	#2 bad ip , 0 good ip
	(ipcalc -c $ip 2>/dev/null &&  return 0) || return 2
}


#this function define the ipbl chain and make sure from the rules are exists
function prepare_ipbl_chain(){
	#to make sure from the ipbl user defined chain is eixts or not , if not a 0 will return if yes a number
	#more than 0 will return, this will not include any check in another chains
	[[ $($IPTABLES -L ipbl  2>/dev/null|wc -l) -lt 1 ]] && $IPTABLES -N ipbl
	#to make sure from the ipbl rule are exists on INPUT chain , will be 0 if not exists or 1 or more than 1 if yes
	#this is user to make sure from that ipbl user-defined chain are exists on the top of iptables INPUT chain (any 
        #packets come to the box from the outside)
	[[ $($IPTABLES -L INPUT | grep ipbl 2>/dev/null|wc -l) -lt 1 ]] && $IPTABLES -I INPUT -j ipbl
}

#this function try to deny the gevin IP
function deny_ip(){
echo "deny ip"
}


#deny ip adr on the fly
if [[ -n ${d} ]]; then
        pout "deny IP ${d}"
	if valid_ip ${d}; then
		prepare_ipbl_chain
		$IPTABLES -I ipbl -s ${d} -j DROP
		if [ "$?" = "0" ]; then
			pout "the IP ${d} were denied"
			if [[ -n ${blit} ]]; then
                        pout "Adding IP ${d} to the local blacklist"
			pout "#blacklisting IP ${d} on $(date)" >> blacklist.lst
			pout "${d}" >> blacklist.lst
			fi

		else 
			pout "error while dening ip ${d}"
		fi		
	else		
		echo "Error: ${d} is not valid ip";
		exit $E_INVALIDIP
	fi
fi

if [[ -n ${fresh} ]]; then
	prepare_ipbl_chain
	while read ipline ; do
        # ignore comment lines #
        echo "$ipline" | grep "^#" >/dev/null 2>&1 && continue
        # if not empty, set the property using declare
        if [[ ! -z "$ipline" ]]; then		
		if valid_ip $ipline; then
			echo "deny IP $ipline"
			$IPTABLES -I ipbl -s $ipline -j DROP
			if [ "$?" = "0" ]; then
                        	echo "the IP $ipline were denied"
			else
				echo "error while dening ip $ipline"
			fi
		else
			echo "Error: $ipline is not valid ip";
		fi			
	fi
        done < $LCLBL

fi;

if [[ -n ${U} ]]; then
	echo "i will check for update"
fi

#deny_blacklist



#EOF
